#!/usr/bin/python
# coding=UTF-8
# noinspection PySingleQuotedDocstring
"""A Python File For Weibo Message Send."""
"""CopyRight © 2020 Luomuyu.All Rights Reserved."""
"""Version:v1.1.1.0"""
"""微博登录获取cookie代码参考CSDN的Bgods：https://blog.csdn.net/songzhilian22/article/details/48396545"""
import requests
import time
import json
import urllib3
import re
import base64
import binascii
import rsa
import getpass
import sys
import msvcrt
import os
import random
import string
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
#使用须知
print('使用须知：\n1.本程序所有数据均经加密后存储在本地文件中，不会将任何数据上传至除微博登录服务器之外的地方\n2.本程序全程使用SSL加密技术保证数据安全\n3.请不要删除此程序同级目录下的任何文件\n更新时间：2020.07.15\n洛沐语')
print('继续使用即代表同意本使用须知')
os.system('pause')
#登陆新浪微博，获取登陆后的Cookie，返回到变量cookies中
config = os.path.isfile("config.ini")
if config == True:
        #读取本地数据、密钥与偏移量
        confp = open("config.ini", "r", encoding="utf-8")
        config = confp.read()
        usn = re.findall('username:[1-9][0-9]{4,}',config,re.S)[0]
        username = re.findall('[1-9][0-9]{4,}',usn,re.S)[0]
        paw = re.findall('pword:[A-z0-9/+=]{8,}',config,re.S)[0]
        pword = re.findall('[A-z0-9/+=]{8,}',paw,re.S)[0]
        oldk = re.findall('key:[A-z0-9!@#$%^&*()]{32}',config,re.S)[0]
        oldkey = re.findall('[A-z0-9!@#$%^&*()]{32}',oldk,re.S)[0]
        oldi = re.findall('iv:[A-z0-9!@#$%^&*()]{16}',config,re.S)[0]
        oldiv = re.findall('[A-z0-9!@#$%^&*()]{16}',oldi,re.S)[0]
        confp.close()
        #密码解密
        key = oldkey.encode('utf-8')
        iv = oldiv.encode('utf-8')
        mode = AES.MODE_CBC
        data = str(pword)
        cipher = AES.new(key,mode,iv)
        base64_decrypted = base64.decodebytes(data.encode('utf-8'))
        una_pkcs7 = unpad(cipher.decrypt(base64_decrypted),AES.block_size,style='pkcs7')
        decrypted_text = str(una_pkcs7, encoding='utf-8')
        pword = decrypted_text
        wbtfp = open("wbtext.ini", "r", encoding="utf-8")
        wbtext = wbtfp.read()
        wbtfp.close()
else:
        print('检测到第一次启动，正在释放文件...')
        confp = open("config.ini", "w", encoding="utf-8")
        username = input(u'请输入手机号：')
        pword = input(u'请输入密码：')
        #创建密钥与偏移量、密码加密
        oldkey = ''.join(random.sample(['Z','Y','X','W','V','U','T','S','R','Q','P','O','N','M','L','K','J','I','H','G','F','E','D','C','B','A','z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g','f', 'e', 'd', 'c', 'b', 'a','9','8','7','6','5','4','3','2','1','0',')','(','*','&','^','%','$','#','@','!'], 32))
        oldiv = ''.join(random.sample(['Z','Y','X','W','V','U','T','S','R','Q','P','O','N','M','L','K','J','I','H','G','F','E','D','C','B','A','z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g','f', 'e', 'd', 'c', 'b', 'a', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', ')', '(', '*', '&','^', '%', '$', '#', '@', '!'], 16))
        key = oldkey.encode('utf-8')
        iv = oldiv.encode('utf-8')
        mode = AES.MODE_CBC
        cipher = AES.new(key,mode,iv)
        data = str(pword)
        pad_pkcs7 = pad(data.encode('utf-8'), AES.block_size, style='pkcs7')
        result = base64.encodebytes(cipher.encrypt(pad_pkcs7))
        encrypted_text = str(result, encoding='utf-8').replace('\n', '')
        pword = encrypted_text
        circletime = input(u'请输入单次消息等待时间（单位:秒)：')
        print('version:1.1.1.0\nkey:'+oldkey+'\niv:'+oldiv+'\nusername:'+username+'\npword:'+pword+'\ncircletime:'+circletime,file=confp)
        confp.close()
        wbtfp = open("wbtext.ini", "w", encoding="utf-8")
        wbtext = input(u'请输入需发送的消息：')
        print(wbtext,file=wbtfp)
        wbtfp.close()
#判断本地cookies
cookies = os.path.isfile("cookies.ini")
if cookies == True:
        #读取cookies
        coofp = open("cookies.ini", "r", encoding="utf-8")
        cookies = coofp.read()
        cookies = cookies.replace('\n', '')
        coofp.close()
        #读取密钥与偏移量
        confp = open("config.ini", "r", encoding="utf-8")
        config = confp.read()
        oldk = re.findall('key:[A-z0-9!@#$%^&*()]{32}', config, re.S)[0]
        oldkey = re.findall('[A-z0-9!@#$%^&*()]{32}', oldk, re.S)[0]
        oldi = re.findall('iv:[A-z0-9!@#$%^&*()]{16}', config, re.S)[0]
        oldiv = re.findall('[A-z0-9!@#$%^&*()]{16}', oldi, re.S)[0]
        confp.close()
        #cookies解密
        key = oldkey.encode('utf-8')
        iv = oldiv.encode('utf-8')
        mode = AES.MODE_CBC
        data = str(cookies)
        cipher = AES.new(key, mode, iv)
        base64_decrypted = base64.decodebytes(data.encode('utf-8'))
        una_pkcs7 = unpad(cipher.decrypt(base64_decrypted), AES.block_size, style='pkcs7')
        decrypted_text = str(una_pkcs7, encoding='utf-8')
        cookies = decrypted_text
        #拼接headers
        wbheaders = {
                'Content-Length': '204800',
                'Cookie': cookies,
                'Host': 'api.weibo.com',
                'Referer': 'https://api.weibo.com/chat/',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
                }
else:
        # 读取本地数据、密钥与偏移量
        confp = open("config.ini", "r", encoding="utf-8")
        config = confp.read()
        usn = re.findall('username:[1-9][0-9]{4,}', config, re.S)[0]
        username = re.findall('[1-9][0-9]{4,}', usn, re.S)[0]
        paw = re.findall('pword:[A-z0-9/+=]{8,}', config, re.S)[0]
        pword = re.findall('[A-z0-9/+=]{8,}', paw, re.S)[0]
        oldk = re.findall('key:[A-z0-9!@#$%^&*()]{32}', config, re.S)[0]
        oldkey = re.findall('[A-z0-9!@#$%^&*()]{32}', oldk, re.S)[0]
        oldi = re.findall('iv:[A-z0-9!@#$%^&*()]{16}', config, re.S)[0]
        oldiv = re.findall('[A-z0-9!@#$%^&*()]{16}', oldi, re.S)[0]
        confp.close()
        #登陆密码解密
        mode = AES.MODE_CBC
        data = str(pword)
        cipher = AES.new(key, mode, iv)
        base64_decrypted = base64.decodebytes(data.encode('utf-8'))
        una_pkcs7 = unpad(cipher.decrypt(base64_decrypted), AES.block_size, style='pkcs7')
        decrypted_text = str(una_pkcs7, encoding='utf-8')
        pword = decrypted_text
        #预登陆获取加密密钥
        preurl = 'http://login.sina.com.cn/sso/prelogin.php?entry=sso&callback=sinaSSOController.preloginCallBack&su=%s&rsakt=mod&client=ssologin.js(v1.4.4)%'+str(username)
        html = requests.get(preurl).content
        servertime = re.findall('"servertime":(.*?),',html.decode('utf-8'),re.S)[0]
        nonce = re.findall('"nonce":"(.*?)"',html.decode('utf-8'),re.S)[0]
        pubkey = re.findall('"pubkey":"(.*?)"',html.decode('utf-8'),re.S)[0]
        rsakv = re.findall('"rsakv":"(.*?)"',html.decode('utf-8'),re.S)[0]
        #数据加密
        username = base64.b64encode(username.encode('utf-8'))
        rsaPublickey = int(pubkey, 16)
        key = rsa.PublicKey(rsaPublickey, 65537) #创建公钥
        message = str(servertime) + '\t' + str(nonce) + '\n' + str(pword) #拼接明文js加密文件中得到
        passwd = rsa.encrypt(message.encode('utf-8'), key) #加密
        passwd = binascii.b2a_hex(passwd) #将加密信息转换为16进制
        #数据发送
        login_url = 'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.4)'
        data = {'entry': 'weibo',
                'gateway': '1',
                'from': '',
                'savestate': '365',
                'userticket': '1',
                'ssosimplelogin': '1',
                'vsnf': '1',
                'vsnval': '',
                'su': username,
                'service': 'miniblog',
                'servertime': servertime,
                'nonce': nonce,
                'pwencode': 'rsa2',
                'sp': passwd,
                'encoding': 'UTF-8',
                'prelt': '115',
                'rsakv' : rsakv,
                'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
                'returntype': 'META'
                }
        html = requests.post(login_url,data=data).content
        urlnew = re.findall("location.replace\(\\'(.*?)\\'",html.decode('GBK'),re.S)[0]
        cookies = requests.get(urlnew).cookies
        cookies = str(cookies)
        ALF = re.findall("ALF=[0-9A-z\-\_\.]*",cookies,re.S)[0]
        SCF = re.findall("SCF=[0-9A-z\-\_\.]*",cookies,re.S)[0]
        SUB = re.findall("SUB=[0-9A-z\-\_\.]*",cookies,re.S)[0]
        SUBP = re.findall("SUBP=[0-9A-z\-\_\.]*",cookies,re.S)[0]
        SUHB = re.findall("SUHB=[0-9A-z\-\_\.]*",cookies,re.S)[0]
        cookies = SCF+'; '+SUB+'; '+SUBP+'; '+SUHB+'; '+ALF
        #拼接headers
        wbheaders = {
            'Content-Length': '204800',
            'Cookie': cookies,
            'Host': 'api.weibo.com',
            'Referer': 'https://api.weibo.com/chat/',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
            }
        #读取密钥与偏移量
        confp = open("config.ini", "r", encoding="utf-8")
        config = confp.read()
        oldk = re.findall('key:[A-z0-9!@#$%^&*()]{32}', config, re.S)[0]
        oldkey = re.findall('[A-z0-9!@#$%^&*()]{32}', oldk, re.S)[0]
        oldi = re.findall('iv:[A-z0-9!@#$%^&*()]{16}', config, re.S)[0]
        oldiv = re.findall('[A-z0-9!@#$%^&*()]{16}', oldi, re.S)[0]
        confp.close()
        #cookies加密
        key = oldkey.encode('utf-8')
        iv = oldiv.encode('utf-8')
        mode = AES.MODE_CBC
        cipher = AES.new(key, mode, iv)
        data = str(cookies)
        pad_pkcs7 = pad(data.encode('utf-8'), AES.block_size, style='pkcs7')
        result = base64.encodebytes(cipher.encrypt(pad_pkcs7))
        encrypted_text = str(result, encoding='utf-8').replace('\n', '')
        cookies = encrypted_text
        #写入cookies
        coofp = open("cookies.ini", "w", encoding="utf-8")
        print(cookies,file=coofp)
        coofp.close()
wburl = 'https://api.weibo.com/webim/groupchat/send_message.json'
clientidurl = "https://web.im.weibo.com/im/handshake?jsonp=jQuery&message=%5B%7B%22version%22%3A%221.0%22%2C%22minimumVersion%22%3A%221.0%22%2C%22channel%22%3A%22%2Fmeta%2Fhandshake%22%2C%22supportedConnectionTypes%22%3A%5B%22callback-polling%22%5D%2C%22advice%22%3A%7B%22timeout%22%3A31536000%2C%22interval%22%3A0%7D%2C%22id%22%3A%222%22%7D%5D"
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
response = requests.get(url=clientidurl,headers=wbheaders,verify=False)
res = response.text
clientid = re.findall('[a-z0-9]{25,35}', res)[0]
wbtfp = open("wbtext.ini", "r", encoding="utf-8")
wbtext = wbtfp.read()
wbtext = wbtext.replace('\n', '')
wbdata = {
    'content': wbtext,
    'id': '4498680306863017',
    'media_type': '0',
    'annotations': '{"webchat":1,"clientid":"'+str(clientid)+'"}',
    'is_encoded': '0',
    'source': '209678993'
    }
wbtfp.close()
#读取等待时间
confp = open("config.ini", "r", encoding="utf-8")
config = confp.read()
cct = re.findall('circletime:[0-9]*',config,re.S)[0]
circletime = re.findall('[0-9]{1,15}',cct,re.S)[0]
#测试发送
requests.post(url=wburl,headers=wbheaders,data=wbdata)
print("已提交发送申请，请检查是否发送成功，下次发送等待"+circletime+"秒")
time.sleep(float(circletime))
#主循环
while True:
    requests.post(url=wburl,headers=wbheaders,data=wbdata)
    print("发送成功，下次发送等待"+circletime+"秒")
    time.sleep(float(circletime))
